package org.commons.communication;

import java.net.Socket;
import java.util.ArrayList;

/**
 *  La classe GetHandler prende una lista di socket gia connessi e per ogni socket crea un thread che gestisce un tipo di opeazione e raccoglie le risposte
 * @author Soulreaver
 *
 */
public class GetHandler {

	private final ArrayList<Socket> connectedSockets;
    private final Worker[] threads;
    private final Packet toSend;
    private Packet responses[];
    private int responsesCollected;
    

	/**
	 *  Il costruttore contiene i seguenti parametri:
	 *  @param connectedSockets socket gia connesso
	 *  @param p pacchetto
	 *
	 */
    public GetHandler(ArrayList<Socket> connectedSockets, Packet p) {
    	this.connectedSockets = connectedSockets;
    	// creazione dell'array di thread Worker, onguno dei quali si occupa della gestione dell'operazione verso un singolo socket
        threads = new Worker[this.connectedSockets.size()];
        responses = new Packet[this.connectedSockets.size()];
        toSend = p;
    }
    
    public void sendRequests() {
        for (int i = 0; i < this.connectedSockets.size(); i++) {
            threads[i] = new Worker(i, this.connectedSockets.get(i));
            threads[i].start();
        }
    }
    /**
	 *  La funzione incrementResponsesCollected() si occupa di incrementare il contatore relativo al numero di risposte ricevute
	 *
	 */
    private synchronized void incrementResponsesCollected() {
    	responsesCollected++;
    }

    /**
     * La funzione getResponses() restituisce un array contenente le risposte
     * @return Packet[]
     */
    public Packet[] getResponses() {
		return responses;
	}
    
    /**
     * La funzione getResponsesCollected() ritorna il numero di risposte ricevute
     * @return int 
     */
	public synchronized int getResponsesCollected() {
		return responsesCollected;
	}
     
     // La classe Worker si occupa dell'invio e della ricezione sul socket 
  	private class Worker extends Thread {
    	
    	private final int index;
    	private final Socket toConnect;
    	
    	private Worker (int index, Socket toConnect) {
    		this.index = index;
    		this.toConnect = toConnect;
    	}
    	
    	@Override
        public void run() {
    		Transport.send(toSend, toConnect);
    		responses[index] = Transport.receive(toConnect);
    		incrementResponsesCollected();
        }
    }

}
